import { Injectable } from '@nestjs/common';
import { AuthClientWeb_SignIn_Dto } from './assets/authClientWeb.dto';
import * as argon2 from 'argon2';
import { CodeSmsd_Service } from '../codeSmsd/codeSmsd.service';
import { Constant_Enum_Enum_UserClient_Status } from '@/common/constants/enum';
import { Class_HttpException_Base } from '@/common/classes/httpException';
import { util_Index_RandomString } from '@/common/util/index';
import {
  IUserClient_JwtStrategyPayload,
  IWxLogin_JwtStrategyPayloaded,
} from '@/common/typeScripts/index';
import { WxChat_Service } from '@/modules/commonModule/wxChat/wxChat.service';
import { UserClient_Service } from '../userClient/userClient.service';
import { InviteRelation } from '../inviteRelation/assets/inviteRelation.entity';
import { EntityManager } from 'typeorm';
import * as base62 from 'base62/lib/ascii';
import { UserClient } from '../userClient/assets/userClient.entity';

@Injectable()
export class AuthClientWeb_Service {
  constructor(
    private wxChat_Service: WxChat_Service,
    private userClient_Service: UserClient_Service,
    private codeSmsd_Service: CodeSmsd_Service,
    private entityManager: EntityManager,
  ) {}

  async authClientWeb_SignIn(body: AuthClientWeb_SignIn_Dto) {
    return await this.entityManager.transaction(async (manage) => {
      if (!body.phone && !body.email) {
        throw new Class_HttpException_Base('邮箱或手机号不能为空');
      }
      const searchQuery = {
        phone: body.phone,
        email: body.email,
      };
      let userClient = await this.userClient_Service.userClient_FindOneByPhoneOrEmail(searchQuery);
      if (body.loginType == 'phonePasswordLgin' || body.loginType == 'emailPasswordLgin') {
        if (!userClient) throw new Class_HttpException_Base('用户名或密码错误');
        const pass = await argon2.verify(userClient.password, body.password);
        if (!pass) throw new Class_HttpException_Base('用户名或密码错误');
      } else if (body.loginType == 'phoneLogin' || body.loginType == 'emailLgin') {
        const { list } = await this.codeSmsd_Service.codeSmsd_FindTen(searchQuery);
        if (new Date().getTime() - new Date(list[0].createTime).getTime() > 120000) {
          throw new Class_HttpException_Base('验证码过期');
        }
        if (
          userClient &&
          userClient.statusUser == Constant_Enum_Enum_UserClient_Status.UserClient_Status_Disable
        ) {
          throw new Class_HttpException_Base('用户已被拉黑');
        }
        if (!userClient) {
          userClient = await manage.save(UserClient, {
            userName: util_Index_RandomString({ length: 7 }),
            phone: body.phone,
            email: body.email,
          });
          userClient.distributionCode = base62.encode(new Date().getTime() + userClient.id * 100);
          await manage.save(UserClient, userClient);
          if (body.code) {
            const inviter = await this.userClient_Service.userClient_FindOneByCode({
              distributionCode: body.distributionCode,
            });
            await manage.save(InviteRelation, {
              invitee: inviter ? inviter : null,
              inviter: userClient,
            });
          }
        }
      }
      const payload: IUserClient_JwtStrategyPayload = {
        userId: userClient.id,
        phone: userClient.phone,
        email: userClient.email,
        statusUser: userClient.statusUser,
        userName: userClient.userName,
        type: 'web',
      };
      return await this.userClient_Service.userClient_WebUtil_ReturnInfoData(userClient, payload);
    });
  }

  authClientWeb_WechatRedirectUrl(
    redirectUri: string,
    scope: 'snsapi_login' | 'snsapi_userinfo' = 'snsapi_userinfo',
  ): string {
    return this.wxChat_Service.wechat_Login(redirectUri, scope);
  }

  async authClientWeb_WechatUserInfo(code: string) {
    const userInfo = await this.wxChat_Service.wechat_UserInfo(code);
    let userWebRecord = await this.userClient_Service.userClient_FindOneByOpenId({
      openid: userInfo.data.openid,
    });
    if (!userWebRecord) {
      userWebRecord = await this.userClient_Service.userClient_WebUtil_Create({
        userName: userInfo.data.nickname,
        openid: userInfo.data.openid,
        headimgurl: userInfo.data.headimgurl,
      });
    }
    const payload: IWxLogin_JwtStrategyPayloaded = {
      userId: userWebRecord.id,
      openid: userWebRecord.openid,
      statusUser: userWebRecord.statusUser,
      type: 'webWx',
    };
    return this.userClient_Service.userClient_WebUtil_ReturnInfoData(userWebRecord, payload);
  }
}
